package org.acompanhamento.pages.workflow;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import jmine.tec.di.annotation.Injected;
import jmine.tec.web.wicket.component.autocomplete.NaturalKeyAutocomplete;
import jmine.tec.web.wicket.pages.form.FormPage;
import jmine.tec.web.wicket.pages.form.FormType;
import jmine.tec.web.wicket.pages.form.WebFormPagesMessages;

import org.acompanhamento.HelpMessages;
import org.acompanhamento.dao.StatusDAO;
import org.acompanhamento.domain.Status;
import org.acompanhamento.domain.StatusTransiction;
import org.acompanhamento.domain.Team;
import org.acompanhamento.domain.Workflow;
import org.acompanhamento.pages.messages.ErrorMessages;
import org.acompanhamento.pages.messages.WebAppMessages;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;

import bancosys.tec.exception.MessageCreator;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.security.annotation.Secure;
import bancosys.tec.security.authorization.UrlPermission;

/**
 * 
 * @author icaro.kume
 *
 */
@Secure(id = "GENERIC_TEAM_MEMBER_URL", permissionType = UrlPermission.class)
public class EditWorkflowPage extends FormPage<Workflow> {

	private List<Status> statuses = new ArrayList<Status>();

	private final List<StatusTransiction> statusTransictions = new ArrayList<StatusTransiction>();

	private final Set<Integer> statusAlterado = new HashSet<Integer>();

	private final Set<Integer> statusTransictionsAlterado = new HashSet<Integer>();


	@Injected
	private StatusDAO statusDao;

	@Injected
	private BaseDAO<StatusTransiction> statusTransictionDao;

	public EditWorkflowPage(PageParameters pageParameters) {
		super(pageParameters);
	}

	public EditWorkflowPage(Page sourcePage, PageParameters sourcePageParameters, Workflow entity, FormType formType) {
		super(sourcePage, sourcePageParameters, entity, formType);

		this.statusTransictions.addAll(entity.getStatusTransictions());
		this.statuses.addAll(this.statusDao.findByWorkflow(entity));
	}

	public EditWorkflowPage(PageParameters pageParameters, Page sourcePage) {
		super(pageParameters, sourcePage);
	}

	@Override
	protected List<Component> createFormComponents() {
		List<Component> components = new ArrayList<Component>();
		this.statuses.add(this.statusDao.createBean());
		this.statusTransictions.add(this.statusTransictionDao.createBean());
		components.add(this.createTextField("name"));
		components.add(new NaturalKeyAutocomplete<>(Team.class, "team"));
		components.add(this.createListStatus());
		components.add(this.createListStatusesTransictions());
		components.add(new Label("titleStatus", WebAppMessages.TITLE_STATUS.create().getMessage()));
		components.add(new Label("titleStatusTransiction", WebAppMessages.TITLE_STATUS_TRANSICTION.create().getMessage()));
		return components;
	}

	private Component createListStatus() {
		WebMarkupContainer containerStatuses = new WebMarkupContainer("containerStatuses");
		ListView<Status> statusesView =  new ListView<Status>("statuses", new PropertyModel<List<Status>>(this, "statuses")) {

			@Override
			protected void populateItem(final ListItem<Status> item) {
				TextField<Object> statusName = EditWorkflowPage.this.createTextField("name", item.getModelObject(), "name");
				statusName.add(new AjaxFormComponentUpdatingBehavior("onblur") {
					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						if(!EditWorkflowPage.this.statusAlterado.contains(item.getIndex())){
							EditWorkflowPage.this.statusAlterado.add(item.getIndex());
							EditWorkflowPage.this.statuses.add(EditWorkflowPage.this.statusDao.createBean());
							EditWorkflowPage.this.updatePainels(target);
						}
					}

				});
				item.add(statusName);

				AjaxLink<Void> ajaxLink = new AjaxLink<Void>("delete") {

					@Override
					public void onClick(AjaxRequestTarget target) {
						for (StatusTransiction statusTransiction : EditWorkflowPage.this.statusTransictions) {
							if(statusTransiction.getToStatus().equals(item.getModelObject()) || statusTransiction.getFromStatus().equals(item.getModelObject())){
								this.error(ErrorMessages.STATUS_ASSOCIADO_TRANSICAO.create(item.getModelObject(), statusTransiction).getMessage());
								target.add(EditWorkflowPage.this.get("feedback"));
								return;
							}
						}

						EditWorkflowPage.this.statuses.remove(item.getModelObject());
						EditWorkflowPage.this.updatePainels(target);
					}
				};
				item.add(ajaxLink);
			}
		};
		containerStatuses.add(new Label("headerStatus", WebAppMessages.HEADER_STATUS.create().getMessage()));
		containerStatuses.add(statusesView);
		statusesView.setOutputMarkupId(true);
		containerStatuses.setOutputMarkupId(true);
		return containerStatuses;
	}

	private void updatePainels(AjaxRequestTarget target) {
		target.add(EditWorkflowPage.this.get("mainForm:mainFieldset:containerStatuses"));
		((WebMarkupContainer)EditWorkflowPage.this.get("mainForm:mainFieldset")).addOrReplace(EditWorkflowPage.this.createListStatusesTransictions());
		target.add(EditWorkflowPage.this.get("mainForm:mainFieldset:containerStatusTransictions"));
	}

	private Component createListStatusesTransictions() {
		WebMarkupContainer containerStatuses = new WebMarkupContainer("containerStatusTransictions");
		ListView<StatusTransiction> statusesView =  new ListView<StatusTransiction>("statusTransictions", new PropertyModel<List<StatusTransiction>>(this, "statusTransictions")) {

			@Override
			protected void populateItem(final ListItem<StatusTransiction> item) {
				List<Status> statusesWithEmpty = new ArrayList<Status>(EditWorkflowPage.this.statuses);
				for (Status status : new ArrayList<Status>(statusesWithEmpty)) {
					if(status.getName() == null || status.getName().isEmpty()){
						statusesWithEmpty.remove(status);
					}
				}
				DropDownChoice<Status> fromStatusDropDown = EditWorkflowPage.this.createDropDown("fromStatus", item.getModelObject(), "fromStatus", statusesWithEmpty, true);
				item.add(fromStatusDropDown);
				fromStatusDropDown.add(new AjaxFormComponentUpdatingBehavior("onblur") {
					@Override
					protected void onUpdate(AjaxRequestTarget target) {

					}
				});
				DropDownChoice<Status> toStatusDropDown = EditWorkflowPage.this.createDropDown("toStatus", item.getModelObject(), "toStatus", statusesWithEmpty, true);
				item.add(toStatusDropDown);
				toStatusDropDown.add(new AjaxFormComponentUpdatingBehavior("onblur") {
					@Override
					protected void onUpdate(AjaxRequestTarget target) {

					}
				});
				TextField<Object> statusName = EditWorkflowPage.this.createTextField("name", item.getModelObject(), "name");
				statusName.add(new AjaxFormComponentUpdatingBehavior("onblur") {
					@Override
					protected void onUpdate(AjaxRequestTarget target) {
						if(!EditWorkflowPage.this.statusTransictionsAlterado.contains(item.getIndex())){
							EditWorkflowPage.this.statusTransictionsAlterado.add(item.getIndex());
							EditWorkflowPage.this.statusTransictions.add(EditWorkflowPage.this.statusTransictionDao.createBean());
							target.add(EditWorkflowPage.this.get("mainForm:mainFieldset:containerStatusTransictions"));
						}
					}
				});
				item.add(statusName);
				AjaxLink<Void> ajaxLink = new AjaxLink<Void>("delete") {

					@Override
					public void onClick(AjaxRequestTarget target) {
						EditWorkflowPage.this.statusTransictions.remove(item.getModelObject());
						target.add(EditWorkflowPage.this.get("mainForm:mainFieldset:containerStatusTransictions"));
					}
				};
				item.add(ajaxLink);
			}
		};
		containerStatuses.add(new Label("headerStatusTransiction", WebAppMessages.HEADER_STATUS_TRANSICTION.create().getMessage()));
		containerStatuses.add(statusesView);
		statusesView.setOutputMarkupId(true);
		containerStatuses.setOutputMarkupId(true);
		return containerStatuses;
	}

	@Override
	protected boolean beforeSave(Workflow target) {
		boolean save = super.beforeSave(target);

		for (Status status : new ArrayList<Status>(this.statuses)) {
			if(status.getName() == null || status.getName().isEmpty()){
				this.statuses.remove(status);
			} else {
				status.setWorkflow(target);
			}
		}

		for (StatusTransiction statusTransaction : new ArrayList<StatusTransiction>(this.statusTransictions)) {
			if(statusTransaction.getName() == null || statusTransaction.getName().isEmpty()){
				this.statusTransictions.remove(statusTransaction);
			}
		}

		return save;
	}

	@Override
	public void save() {
		Workflow target = this.getMergedEntity();
		if (!this.beforeSave(target)) {
			return;
		}
		target.getPersister().save();

		// Se o cadastro for de edição, apos salvar direcionar para a página de
		// pesquisa
		this.redirectAfterSave();
		// não queremos isso =)
		this.getSession().info(WebFormPagesMessages.INFO_ENTITY_SAVE_SUCCESS.create().getMessage());

		for (Status status : this.statuses) {
			status.getPersister().save();
		}

		List<Status> savedStatuses = this.statusDao.findByWorkflow(target);
		for (Status status : savedStatuses) {
			if(!this.statuses.contains(status)){
				status.getPersister().remove();
			}
		}

		for (StatusTransiction statusTransaction : this.statusTransictions) {
			statusTransaction.getPersister().save();
		}

		target.getStatusTransictions().clear();
		target.getStatusTransictions().addAll(this.statusTransictions);
		target.getPersister().save();

	}

	public List<Status> getStatuses() {
		return this.statuses;
	}

	public void setStatuses(List<Status> statuses) {
		this.statuses = statuses;
	}

	@Override
	protected MessageCreator getHelpTextCreator() {
		return HelpMessages.WORKFLOW_EDIT;
	}
}
